﻿using System;
using System.Windows.Controls;
using Simp.CodeModel;
using Simp.CodeModel.CoreFunctions.Sequences;
using System.Windows;
using System.Windows.Shapes;
using Simp.CodeModel.CoreFunctions;
using System.Windows.Media;
using System.Collections.Generic;

namespace Simp.GraphModel
{
	/// <summary>Encapsulate a line function.</summary>
	public class PolylineFunction : IElementProducerFunction
	{
		private static readonly string[] PARAMETER_NAMES = new[] { "points", "isClosing" };
		private static readonly IFunctionParameterBinding[] DEFAULT_BINDING;

		/// <summary>Static constructor, initializing static fields.</summary>
		static PolylineFunction()
		{
			IFunctionParameterBinding defaultIsClosing = FunctionHelper.FunctionParameterBindingFactory.Build(
				PARAMETER_NAMES[1],
				new BoundFunctionCalling(new TrueFunction()));

			DEFAULT_BINDING = new IFunctionParameterBinding[]
			{
				defaultIsClosing
			};
		}

		#region IFunction Members
		string IFunction.FunctionName
		{
			get { return "Polyline"; }
		}

		string[] IFunction.ParameterNames
		{
			get { return PARAMETER_NAMES; }
		}

		IFunctionParameterBinding[] IFunction.DefaultParameterValues
		{
			get { return DEFAULT_BINDING; }
		}

		IFunction IFunction.Simplify(SimplificationMode simplificationMode, params IFunction[] parameters)
		{
			return null;
		}

		IFunction IFunction.AcceptVisitor(IFunctionVisitor visitor)
		{
			return null;
		}
		#endregion

		#region IElementProducer Members
		UIElement IElementProducerFunction.Produce(params IFunction[] parameters)
		{
			FunctionHelper.ValidateParameters(this, parameters);

			IFunction pointsParam = parameters[0];
			IFunction isClosingParam = parameters[1];
			ISequenceAccessor accessor = FunctionHelper.GetAccessor(pointsParam);
			bool? isClosing = FunctionHelper.TryGetBooleanValue(isClosingParam);

			if (accessor != null && isClosing != null)
			{
				PointCollection pointList = new PointCollection(accessor.Count);

				foreach (IFunction pointFunction in
					new SyncSimplifyingSequenceAccessor(SimplificationMode.AllowApproximation, accessor))
				{
					double x, y;

					if (!PointFunction.TryGetCartesian(pointFunction, out x, out y))
					{
						return null;
					}

					Point point = new Point(x, y);

					pointList.Add(point);
				}
				if (isClosing.Value)
				{
					Polygon polygon = new Polygon { Stroke = GraphicHelper.DefaultStroke, Points = pointList };

					return polygon;
				}
				else
				{
					Polyline polyline = new Polyline { Stroke = GraphicHelper.DefaultStroke, Points = pointList };

					return polyline;
				}
			}

			return null;
		}
		#endregion
	}
}